Abraxus's Blog

Bamboo Fox Ransomware Write Up

Details:

Points: 500

Jeopardy style CTF

Category: Reversing

Write up:

This challenge had no description whatsoever, just a Zip file. When first unzipping the downloaded file I ended up with two files, flag.enc and task.pyc.

Running task.pyc with python 2+ did not work, python3 worked but had an error. From this I concluded that the file was a python3 file and used uncompyle6 and got the code below.

$ uncompyle6 task.pyc

# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.8.6 (default, Sep 25 2020, 09:36:53) 
# [GCC 10.2.0]
# Embedded file name: task.py
# Compiled at: 2021-01-14 09:13:24
# Size of source mod 2**32: 420 bytes
(lambda data, key, iv: if len(data) != 0:
(lambda key, iv, data, AES: open('flag.enc', 'wb').write(AES.new(key, AES.MODE_CBC, iv).encrypt(lambda x: x + b'\x00' * (16 - len(x) % 16)(data))))(data[key:key + 16], data[iv:iv + 16], open('flag.png', 'rb').read(), __import__('Crypto.Cipher.AES').Cipher.AES) # Avoid dead code: lambda fn: __import__('os').remove(fn)('task.py'))(__import__('requests').get('https://ctf.bamboofox.tw/rules').text.encode(), 99, 153)
# okay decompiling task.pyc

I noticed that the python referenced the flag.png file however that file was not provided so I knew that I would need to reverse the flag.enc file to produce flag.png.

The first thing I noticed was that the python was requesting the rules page of the CTF so I opened postman and did the get request, the response was:

<!DOCTYPE html>
<html>

<head>
	<title>BambooFox CTF</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<link rel="shortcut icon"
		href="/files/626f05557db4b8f323a06e0dfc7676d8/favicon-32x32-a56b8e05e1d057431bef7fd212f394a18049e895a4db003909e9448478b8167d.png"
		type="image/x-icon">
	<link rel="stylesheet" href="/themes/core/static/css/fonts.min.css?d=aa35138e">
	<link rel="stylesheet" href="/themes/core/static/css/main.min.css?d=aa35138e">
	<link rel="stylesheet" href="/themes/core/static/css/core.min.css?d=aa35138e">


...

Looking at the python I saw that this was getting passed as data to the lambda function, I then opened up a python interpreter and saved the request response as data so that I could test the rest of the code. I then noticed that 99 was being passed as key and 153 was being passed as iv so I set up the python accordingly:

Python 3.8.6 
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> data = __import__('requests').get('https://ctf.bamboofox.tw/rules').text.encode()
>>> key = 99
>>> iv = 153

I then checked to see the two strings generated in the lambda function:

>>> data[key:key+16]
b'ewport" content='
>>> data[iv:iv+16]
b'">\n\t<link rel="s'

Both of these values were getting passed to another lambda and were then being used in order to create an AES (Advanced Encryption System) object which is from python's crypto module. After some research and refreshing my knowledge on AES I saw that as long as I had the key and iv I would be able to decrypt anything encrypted with AES. At this point I just put everything in a script and read in the flag.enc file and wrote the decrypted bytes into flag.png. Which resulted in the following code:

# Gets the data from the webpage
data = __import__('requests').get('https://ctf.bamboofox.tw/rules').text.encode()

key = 99

iv = 153

# Creates the AES object
AES = __import__('Crypto.Cipher.AES').Cipher.AES

# gets the real key from data
key = data[key:key+16]

# gets the real iv from data
iv = data[iv:iv+16]

# opens flag.enc so we can read bytes
ofile = open('flag.enc', 'rb')

# creates the decryption tool 
decrypt = AES.new(key, AES.MODE_CBC, iv)

# opens the flag.png file so we can append bytes to it
nfile = open('flag.png', 'ab')

while True:
	# read 16 bytes at a time
	chunk = ofile.read(16)
	if len(chunk) == 0:
		break
	# decrypt the chunk and write it to the file
	nfile.write(decrypt.decrypt(chunk))

This python reads in the flag.enc file and decrypts it using the standard that was used to encrypt it in the original python code, the key and iv are pulled from the rules page of the CTF.

Once I had finished the python script I ran it and ended up with this photo:

Flag Photo

I then tried several different things to try to find the flag on the photo:

$ exiftool flag.png     

ExifTool Version Number         : 12.13
File Name                       : flag.png
Directory                       : .
File Size                       : 1174 KiB
File Modification Date/Time     : 2021:01:15 23:40:00-05:00
File Access Date/Time           : 2021:01:15 23:40:04-05:00
File Inode Change Date/Time     : 2021:01:15 23:40:00-05:00
File Permissions                : rw-r--r--
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 980
Image Height                    : 746
Bit Depth                       : 8
Color Type                      : RGB with Alpha
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Warning                         : [minor] Trailer data after PNG IEND chunk
Image Size                      : 980x746
Megapixels                      : 0.731
$ strings flag.png | grep -e 'flag'  

exiftool did not show any comments or unusual data, and there were no strings in the png that contained flag. I then attempted to do a binwalk hoping for a hidden file inside the png.

$ binwalk ./flag.png 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 980 x 746, 8-bit/color RGBA, non-interlaced
41            0x29            Zlib compressed data, default compression
808562        0xC5672         PNG image, 980 x 492, 8-bit/color RGBA, non-interlaced
808603        0xC569B         Zlib compressed data, default compression

Here i noticed that there was another smaller PNG within the png so I ran:

$ binwalk -D=".*" ../flag.png   

This then led to the following photo to be extracted:

Flag Photo